module.exports = class MyPromise {
    #status = 'pending'
    #result = null
    #error = null
    #onFulfilledQueue = []
    #onRejectedQueue = []
    #nextPQueue = []
    // resolve调用
    #resolve = function (res) {

        const clearFirst = (res) => {
            // 这里是：then返回的新的promise的resolve，因为本promise已经resolve了，后面的链式调用的promise都应该是resolve的
            // 但这里理应是then微任务之后的操作，但js做不到创建微任务，用了个setTimeout代替
            queueMicrotask(() => {
                // 把监听器的结果向下传递
                if (this.#nextPQueue[0].#onFulfilledQueue.length) this.#nextPQueue[0].#resolve(res)
                // 新包装的promise不做保留
                this.#nextPQueue.shift()
            });
        }

        // 如果状态没改变，那就改变状态并保存结果（promise状态只能更改一次）
        if (this.#status === 'pending') {
            this.#result = res
            this.#status = 'fulfilled'
        }

        queueMicrotask(() => {
            // 清理事件队列：如果没有有对应监听器（说明构造函数中没有异步操作，promise已经更改了状态，但还没注册上监听器），应该等待then方法调用，注册上监听器后再回来执行
            while (this.#onFulfilledQueue.length) {
                // 执行监听器并获取到返回值
                let res = this.#onFulfilledQueue[0](this.#result)
                // 监听器只执行一次，不做保留
                this.#onFulfilledQueue.shift()
                // 如果监听器返回是个promise，应该在生产一个微任务，且取值
                if (res && res instanceof MyPromise) {
                    // c++: NewPromiseResolveThenableJobTask
                    queueMicrotask(() => {
                        // PromiseResolveThenableJobTask
                        queueMicrotask(() => {
                            res.then((res) => {
                                clearFirst(res)
                            })
                        })
                    })
                }
                // 如果只是个thenable，就取值
                else if (res && res.then) {
                    res.then((res) => {
                        clearFirst(res)
                    })
                }
                // 否则直接链式调用
                else {
                    clearFirst(res)
                }
            }
        })
    }
    // 与上面resolve同理
    #reject = function (err) {
        if (this.#status === 'pending') {
            this.#error = err
            this.#status = 'rejected'
        }

        // HostPromiseRejectionTracker
        if (!this.#onRejectedQueue.length) throw new Error('Unhandled promise rejection')
        queueMicrotask(() => {
            while (this.#onRejectedQueue.length) {
                this.#onRejectedQueue[0](this.#error)
                this.#onRejectedQueue.shift()

                queueMicrotask(() => {
                    // 不同点1：错误不会向下传递，而是resolve下一个promise
                    if (this.#nextPQueue[0].#onFulfilledQueue.length) this.#nextPQueue[0].#resolve()
                    this.#nextPQueue.shift()
                });
            }
        })
    }

    // 构造器：
    constructor(cb = () => { }) {
        // 同步执行回调函数
        cb(this.#resolve.bind(this), this.#reject.bind(this))
    }

    // then方法：
    then(onFulfilled = (e) => e, onRejected = (e) => e) {
        // 1.添加两个监听器
        this.#onFulfilledQueue.push(onFulfilled)
        this.#onRejectedQueue.push(onRejected)

        // 3.如果promise已经返回结果，那就执行对应的监听器
        if (this.#status === 'fulfilled') this.#resolve()
        if (this.#status === 'rejected') this.#reject()

        let np = new MyPromise()
        // 2.返回一个新的promise
        this.#nextPQueue.push(np)
        return np
    }

    catch(onRejected = err => err) {
        return this.then(undefined, onRejected)
    }

    finally(cb = e => e) {
        return this.then(cb, cb)
    }

    static resolve(e) {
        return new MyPromise(_ => _(e))
    }

    static reject(e) {
        return new MyPromise((resolve, _) => _(e))
    }
}